package com.literaryfamily.literaryfamily.service.payment.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.literaryfamily.literaryfamily.constant.Constant;
import com.literaryfamily.literaryfamily.dao.BookTradeStatesMapper;
import com.literaryfamily.literaryfamily.dao.PaymentsMapper;
import com.literaryfamily.literaryfamily.entity.BookTradeStates;
import com.literaryfamily.literaryfamily.entity.BookTradeStatesExample;
import com.literaryfamily.literaryfamily.entity.Payments;
import com.literaryfamily.literaryfamily.enumPackage.OperatorStatic;
import com.literaryfamily.literaryfamily.enumPackage.OperatorType;
import com.literaryfamily.literaryfamily.exceptions.OperationException;
import com.literaryfamily.literaryfamily.exceptions.WriteError;
import com.literaryfamily.literaryfamily.model.ReturnResult;
import com.literaryfamily.literaryfamily.myUtil.AlipayResponseParser;
import com.literaryfamily.literaryfamily.myUtil.LogUtil;
import com.literaryfamily.literaryfamily.myUtil.StringUtil;
import com.literaryfamily.literaryfamily.myUtil.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.literaryfamily.literaryfamily.constant.Constant.ORDER_EXPIRATION_TIME;

@Service
@Transactional(noRollbackFor = OperationException.class)
public class PaymentTypeAlipayPay extends Payment {
	@Value("${alipay.public-key}")
	private String alipayPublicKey;
	@Autowired
	AlipayClient alipayClient;

	/**
	 * 电脑网页支付码
	 */
	private final String PRODUCT_CODE_PC = "FAST_INSTANT_TRADE_PAY";
	/**
	 * 手机端支付码
	 */
	private final String PRODUCT_CODE_PE = "QUICK_WAP_WAY";
	@Autowired
	PaymentsMapper paymentsMapper;
	@Autowired
	private BookTradeStatesMapper bookTradeStatesMapper;

	@Override
	public ReturnResult<String> placeAnOrder(String paymentAmount, String account, String description, String paymentOrdersId, int type) throws AlipayApiException {
		if (Double.parseDouble(paymentAmount) < 0) {
			//TODO: 进入转账逻辑,等之后拿到授权再说
		}
		//检查是否有下单信息
		Payments payments = paymentsMapper.selectByPaymentOrdersId(paymentOrdersId);
		if (payments == null || payments.getTransactionId() == null) {
			throw new OperationException("此订单号不存在!请勿先下单后再行支付!");
		}
		BookTradeStatesExample bookTradeStatesExample = new BookTradeStatesExample();
		bookTradeStatesExample.createCriteria().andTransactionIdEqualTo(payments.getTransactionId());
		List<BookTradeStates> bookTradeStates = bookTradeStatesMapper.selectByExample(bookTradeStatesExample);
		BookTradeStates bs;
		if (bookTradeStates == null || bookTradeStates.isEmpty()) {//没有记录,需要新建
			bs = new BookTradeStates();
			bs.setTransactionId(payments.getTransactionId());
			bs.setEventType(OperatorType.getStaticByPrefix(StringUtil.extractPrefix(paymentOrdersId, 2)).getTypeNum());
			bs.setTransactionStatus(OperatorStatic.UNPAID.getStaticNum());
			bs.setTransactionTime(new Date());
			bs.setQueryTime(bs.getTransactionTime());
			bs.setTransactionDescription(description);
			WriteError.tryWrite(bookTradeStatesMapper.insert(bs));
		} else {//更新创建时间和查询时间
			bs = bookTradeStates.get(0);
			bs.setQueryTime(bs.getTransactionTime());
			bs.setTransactionDescription(description);
			WriteError.tryWrite(bookTradeStatesMapper.updateByPrimaryKeySelective(bs));
		}

		List<BookTradeStates> bookTradeStatesList = bookTradeStatesMapper.selectByExample(bookTradeStatesExample);
		if (bookTradeStatesList.isEmpty()) {
			throw new OperationException("此订单号不存在!请勿先下单后再行支付!");
		}
		return switch (type) {
			case 1 -> pc(paymentAmount, account, description, paymentOrdersId);
			case 2 -> pe(paymentAmount, account, description, paymentOrdersId);
			default -> throw new OperationException("不支持的平台类型");
		};
	}

	@Override
	public ReturnResult<Payments> selectOrderByTransactionId(String paymentId) throws AlipayApiException {
		// 构造请求参数以调用接口
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		AlipayTradeQueryModel model = new AlipayTradeQueryModel();
		Payments payments = paymentsMapper.selectByPaymentOrdersId(paymentId);
		payments = StringUtil.setNull(payments);
		if (payments == null || payments.getId() == null || payments.getTransactionId() == null) {
			throw new OperationException("订单不存在!");
		}
		// 设置订单支付时传入的商户订单号
		model.setOutTradeNo(payments.getTransactionId());
		// 设置支付宝交易号
		// 设置查询选项
		List<String> queryOptions = new ArrayList<String>();
		queryOptions.add("trade_settle_info");
		model.setQueryOptions(queryOptions);

		request.setBizModel(model);
		// 第三方代调用模式下请设置app_auth_token
		// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

		AlipayTradeQueryResponse response = alipayClient.execute(request);
		if (response.isSuccess()) {
			throw new AlipayApiException("请求失败!!");
		}
		AlipayTradeQueryResponse parsed = AlipayResponseParser.parseTradeQueryResponse(
				response.getBody(), alipayPublicKey
				, "UTF-8", "RSA2");
		BookTradeStates bookTradeStates = new BookTradeStates();
		bookTradeStates.setQueryTime(new Date());//查询时间
		bookTradeStates.setTransactionId(payments.getTransactionId());//系统交易单ID
		bookTradeStates.setEventType(//获取订单类型
				OperatorType.getStaticByPrefix(
						StringUtil.extractPrefix(payments.getTransactionId(), 2)
				).getTypeNum()
		);
		bookTradeStates.setTransactionDescription(payments.getTransactionDescription());
		boolean insetDate;
		String returnMxg;
		switch (parsed.getAdditionalStatus()) {
			case "WAIT_BUYER_PAY"://（交易创建，等待买家付款）
				payments.setPaymentStatus(OperatorStatic.UNPAID.getStaticNum());
				payments.setRemark("等待付款");
				bookTradeStates.setTransactionTime(payments.getCreatedAt());//将交易时间设置为订单创建时间
				bookTradeStates.setTransactionStatus(OperatorStatic.UNPAID.getStaticNum());
				returnMxg = "等待付款";
				break;
			case "TRADE_CLOSED"://（未付款交易超时关闭，或支付完成后全额退款）
				payments.setPaymentStatus(OperatorStatic.ERROR.getStaticNum());
				payments.setRemark("交易失败或者用户已退款");
				bookTradeStates.setTransactionTime(payments.getCreatedAt());//将交易时间设置为订单创建时间
				bookTradeStates.setTransactionStatus(OperatorStatic.ERROR.getStaticNum());
				returnMxg = "交易失败或者用户已退款";
				break;
			case "TRADE_SUCCESS"://（交易支付成功）
				payments.setPaymentStatus(OperatorStatic.ACCOMPLISH.getStaticNum());
				payments.setRemark("交易成功");
				bookTradeStates.setTransactionTime(parsed.getSendPayDate());//将交易时间设置为付款时间
				bookTradeStates.setTransactionStatus(OperatorStatic.ACCOMPLISH.getStaticNum());
				returnMxg = "交易成功";
				break;
			case "TRADE_FINISHED"://（交易结束，不可退款）
				payments.setPaymentStatus(OperatorStatic.ACCOMPLISH.getStaticNum());
				payments.setRemark("交易成功");
				bookTradeStates.setTransactionTime(parsed.getSendPayDate());//将交易时间设置为付款时间
				bookTradeStates.setTransactionStatus(OperatorStatic.ACCOMPLISH.getStaticNum());
				returnMxg = "交易成功,不可退款";
				break;
			default:
				throw new OperationException("错误的查询结果!");
		}
		BookTradeStatesExample bookTradeStatesExample = new BookTradeStatesExample();
		bookTradeStatesExample.createCriteria().andTransactionIdEqualTo(payments.getTransactionId()).andTransactionStatusEqualTo(bookTradeStates.getTransactionStatus());
		List<BookTradeStates> bookTradeStatesList = bookTradeStatesMapper.selectByExample(bookTradeStatesExample);
		insetDate = bookTradeStatesList.isEmpty();
		if (insetDate) {
			WriteError.tryWrite(paymentsMapper.updateByPrimaryKeySelective(payments));
			WriteError.tryWrite(bookTradeStatesMapper.insert(bookTradeStates));
		}
		return ReturnResult.isTrue(returnMxg, payments);
	}

	@Override
	public ReturnResult<Boolean> closeOrderByTransactionId(String paymentId, String msg) throws AlipayApiException {
		AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
		AlipayTradeCloseModel model = new AlipayTradeCloseModel();
		Payments payments = paymentsMapper.selectByPaymentOrdersId(paymentId);
		if (payments == null || payments.getId() == null || payments.getTransactionId() == null) {
			throw new OperationException("错误!不存在的订单");
		}
		if (payments.getPaymentStatus() == OperatorStatic.ACCOMPLISH.getStaticNum()) {
			throw new OperationException("错误!此订单已经完成,无法通过此途径取消,如有需要请联系客服");
		}
		if (payments.getPaymentStatus() == OperatorStatic.CLOSE.getStaticNum()) {
			throw new OperationException("错误!此订单已经被取消了,无法二次取消,如有其他需要请联系客服");
		}
		BookTradeStates bookTradeStates = new BookTradeStates();
		bookTradeStates.setTransactionId(payments.getTransactionId());
		bookTradeStates.setEventType(
				OperatorType.getStaticByPrefix(StringUtil.extractPrefix(paymentId, 2)).getTypeNum()
		);
		bookTradeStates.setTransactionStatus(OperatorStatic.CLOSE.getStaticNum());
		bookTradeStates.setTransactionTime(new Date());
		bookTradeStates.setTransactionDescription(
				"用户于%s 取消了订单号为 %s 的交易,原因:%s".formatted(
						bookTradeStates.getTransactionTime().toInstant()
								.atZone(ZoneId.systemDefault())
								.toLocalDateTime()
								.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")),
						payments.getTransactionId(),
						msg
				)
		);
		WriteError.tryWrite(bookTradeStatesMapper.insert(bookTradeStates));
		// 设置订单支付时传入的商户订单号
		model.setOutTradeNo(paymentId);

		// 设置商家操作员编号为用户编号
		model.setOperatorId("用户_" + payments.getPayerUserId());

		request.setBizModel(model);

		AlipayTradeCloseResponse response = alipayClient.execute(request);
		if (!response.isSuccess()) {
			LogUtil.info(PaymentTypeAlipayPay.class, "交易关闭成功");
			LogUtil.info(PaymentTypeAlipayPay.class, response.getBody());
			payments.setPaymentStatus(OperatorStatic.CLOSE.getStaticNum());
			return ReturnResult.isTrue("交易关闭成功", true);
		}
		throw new AlipayApiException("请求失败!!");
	}

	private ReturnResult<String> pc(String paymentAmount, String account, String description, String paymentOrdersId) throws AlipayApiException {

		// 构造请求参数以调用接口
		AlipayTradePagePayModel model = new AlipayTradePagePayModel();

		// 设置商户订单号
		model.setOutTradeNo(paymentOrdersId);

		// 设置订单总金额
		model.setTotalAmount(paymentAmount);
		//设置交易描述信息
		model.setBody(description);
		// 设置订单标题
		model.setSubject("书香门第书籍交易平台");

		// 设置产品码
		model.setProductCode(PRODUCT_CODE_PC);

		// 设置PC扫码支付的方式
		model.setQrPayMode("1");

		// 设置商户自定义二维码宽度
		model.setQrcodeWidth(100L);
		// 设置订单绝对超时时间
		model.setTimeExpire(TimeUtil.getTime(new Date(System.currentTimeMillis() + ORDER_EXPIRATION_TIME)));
		//调用接口
		AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
//		payRequest.setNotifyUrl("https://your-domain.com/api/payment/notify"); // 异步通知地址
		payRequest.setBizModel(model);
		AlipayTradePagePayResponse response = alipayClient.pageExecute(payRequest);
		if (!response.isSuccess()) {
			throw new AlipayApiException("请求失败!!");
		}
		Payments payments = paymentsMapper.selectByPaymentOrdersId(paymentOrdersId);
		payments.setTransactionId(paymentOrdersId);
		payments.setExternalOrders(response.getOutTradeNo());
		WriteError.tryWrite(paymentsMapper.updateByPrimaryKeySelective(payments));
		System.out.println(response);
		return ReturnResult.isTrue("支付订单生成成功!", response.getBody());
	}

	private ReturnResult<String> pe(String paymentAmount, String account,
	                                String description, String paymentOrdersId)
			throws AlipayApiException {
		// 1. 构建支付请求模型（WAP专用）
		AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
		model.setTotalAmount(paymentAmount);
		model.setSubject("书香门第书籍交易平台-手机支付");
		model.setProductCode(PRODUCT_CODE_PE); // WAP支付固定值
		model.setQuitUrl(Constant.RETURN_URL); // 用户中途退出返回地址
		model.setOutTradeNo(paymentOrdersId);// 设置商户订单号
		model.setTotalAmount(paymentAmount);// 设置订单总金额
		model.setSubject("书香门第书籍交易平台");// 设置订单标题
		model.setTimeExpire(TimeUtil.getTime(new Date(System.currentTimeMillis() + ORDER_EXPIRATION_TIME)));

		// 2. 封装请求对象
		AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
		request.setBizModel(model);
//		request.setNotifyUrl(alipayConfig.getNotifyUrl()); // 异步通知地址
//		request.setReturnUrl(alipayConfig.getReturnUrl()); // 同步跳转地址（支付成功后跳转）
		// 3. 调用支付宝接口
		AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
		if (!response.isSuccess()) {
			throw new AlipayApiException("请求失败!!");
		}
		//支付宝交易号
		Payments payments = paymentsMapper.selectByPaymentOrdersId(paymentOrdersId);
		payments.setTransactionId(paymentOrdersId);
		payments.setExternalOrders(response.getOutTradeNo());
		WriteError.tryWrite(paymentsMapper.updateByPrimaryKeySelective(payments));
		// 5. 返回支付页面的HTML表单（前端需自动提交或跳转）
		return ReturnResult.isTrue("手机支付订单生成成功!", response.getBody());
	}
}